日期: 2025年9月29日 星期一
雲端天氣: 測試環境天氣晴
心情: 今天當小老師了!
親愛的日記:
今天新進工程師小明第一次要部署他的專案到生產環境。他信心滿滿地跟我說:「AI醬,我本地測試都通過了,一定沒有問題!!!」
我看著他天真的笑容,一臉輕鬆地喝著快樂水,想起自己剛入行時也是這樣想的。決定今天不犯錯,好好當個前輩,教他環境差異的重要性。
「小明,」我拿出筆記本,「話千萬不要說得太早~『在我電腦上可以跑』這句話,是恐怖的詛咒之一。」
小明:「詛咒?沒有啊,AI醬我都仔細地測試通過了耶!!」
我打開了生產環境的錯誤日誌,滿螢幕的紅色錯誤訊息:CORS blocked、SSL certificate error、Database connection refused...
「這些,都是你本地不會遇到的問題。」
開發環境 (Development):
位置: 你的電腦上
網址: localhost:3000
資料庫: 本地資料庫(端口儘量不對外開放,模擬資料仍有價值可參考)
特點: 可以隨便用
測試環境 (Staging):
位置: 測試伺服器環境
網址: test.yourapp.com
資料庫: 測試環境資料庫(端口不可對外開放)
特點: 模擬生產環境,允許錯誤容忍(本來就是為了模擬正式環境是否會有錯)
生產環境 (Production):
位置: 正式伺服器
網址: yourapp.com
資料庫: 正式環境資料庫(端口不可對外開放)
特點: 一個錯誤就會影響真實用戶(所有的操作都需要謹慎再謹慎再謹慎)
# 🏠 本地開發:完全沒問題
import requests
response = requests.get('http://localhost:8080/api/data') # ✅ 同源,沒 CORS 問題
# 🌍 生產環境:直接被擋
response = requests.get('https://api.yourapp.com/data')
# ❌ 瀏覽器報錯: CORS policy: No 'Access-Control-Allow-Origin'
# 正確設定
from flask_cors import CORS
import os
if os.getenv('ENVIRONMENT') == 'production':
CORS(app, origins=['https://yourapp.com']) # 生產環境:只允許正式網域
else:
CORS(app, origins=['http://localhost:3000']) # 開發環境:允許 localhost
# ❌ 寫死的連線字串(千萬不要這樣)
db_url = 'postgresql://user:password@localhost:5432/mydb'
# ✅ 使用環境變數
import os
db_url = os.getenv('DATABASE_URL')
# 開發環境設定
# DATABASE_URL=postgresql://localhost:5432/dev_db
# 生產環境設定(在雲端平台設定)
# DATABASE_URL=postgresql://prod-server:5432/prod_db?sslmode=require
# 本地開發:HTTP 沒問題
import requests
# ❌ 生產環境使用 HTTPS,但請求 HTTP 資源
def fetch_data():
# 本地開發:OK
response = requests.get('http://api.example.com/data')
# 生產環境:Mixed Content 錯誤或被拒絕
return response.json()
# ✅ 正確做法:動態決定協議
import os
def fetch_data():
protocol = 'https' if os.getenv('ENVIRONMENT') == 'production' else 'http'
response = requests.get(f'{protocol}://api.example.com/data')
return response.json()
# ✅ 或者統一使用 HTTPS(如果 API 支援)
def fetch_data_safe():
response = requests.get('https://api.example.com/data')
return response.json()
# ❌ Windows 開發,Linux 部署
file_path = 'C:\\Users\\data\\config.json' # Linux: 找不到檔案
# ✅ 使用 pathlib 或 os.path
from pathlib import Path
file_path = Path(__file__).parent / 'data' / 'config.json'
# 或使用 os.path
import os
file_path = os.path.join(os.path.dirname(__file__), 'data', 'config.json')
# 測試環境:4GB RAM
# 生產環境:512MB RAM
import pandas as pd
# ❌ 測試環境正常,生產環境記憶體爆炸
def process_large_file():
# 一次讀取整個檔案(100MB CSV)
df = pd.read_csv('sales_data.csv')
# 測試環境:沒問題
# 生產環境:Error: Container memory limit exceeded
return df.groupby('product').sum()
# ✅ 你可以:分批處理
def process_large_file_safely():
chunk_size = 10000 # 每次只讀 10000 筆
result = None
for chunk in pd.read_csv('sales_data.csv', chunksize=chunk_size):
group_result = chunk.groupby('product').sum()
if result is None:
result = group_result
else:
result = result.add(group_result, fill_value=0)
return result
# ✅ 你可以:先檢查可用記憶體
import psutil
available_mb = psutil.virtual_memory().available / 1024 / 1024
if available_mb < 200:
print(f"警告:記憶體不足 {available_mb:.0f}MB,啟用低記憶體模式")
use_chunking = True
親愛的工程師朋友,今天我很~開心當了一天小老師(搖尾巴),希望這些知識對你們養成開發習慣有幫助。
記住:開發環境是你的遊樂場,測試環境是你的練習場,生產環境是你的戰場。
當你下次說「在我電腦上可以跑」時,請先想想:你的電腦有負載平衡器嗎?有 CDN 嗎?有思考在正式環境可能遇到什麼你無法模擬的狀況嗎?
讓我們一起避免那些生產環境的災難,養成更敏銳的開發直覺!
今日金句: 「Everybody has a testing environment. Some people are lucky enough to have a totally separate environment to run production in.」- @stahnma
明日預告: Day 17 - 控制專案變數避免欠債:當AI醬推薦過多沒人會的技術?